package net.jiastudy.web.portal.controller;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpUtil;
import net.jiastudy.core.utils.JwtUtil;

@Controller
public class LoginController extends BasePortalController {

	@Value("${login.jwt.token.expireTime}")
	private Integer tokenExpireTime;
	@Value("${cas.server.host.validate_url}")
	private String casHostValidateUrl;
	@Value("${cas.server.host.login_url}")
	private String casHostLoginUrl;
	@Value("${portal.enable}")
	private boolean portalEnable;
	@Value("${portal.server.host.url}")
	private String portalServerHostUrl;
	@Value("${version}")
	private String version;

	@GetMapping("/error")
	public String error() {
		return "error";
	}

	@GetMapping("/homepage")
	public String homepage() {
		return "redirect:/index.html?v=" + version;
	}

	@GetMapping("/login")
	public String login() {
		if (portalEnable) {
			return "redirect:" + portalServerHostUrl;
		}
		return "redirect:/#/login";
	}

	@GetMapping("/login/cas")
	public String loginCas(String ticket, String service, HttpServletRequest request) {
		StringBuilder urlBuilder = new StringBuilder(this.getService(request));
		if (null == service || service.isEmpty() || service.equals("")) {
			service = "/!/";
		}
		if (StrUtil.isEmpty(ticket)) {
			urlBuilder.append("?service=");
			service = service.replace("#", "!");
			urlBuilder.append(service);
			return "redirect:" + casHostLoginUrl + "?service=" + HttpUtil.encodeUtf8(urlBuilder.toString());
		}
		Map<String, Object> paramMap = new HashMap<>();
		if (!StrUtil.isEmpty(ticket) && !StrUtil.equals(service, "/!/")) {
			urlBuilder.append("?service=");
			urlBuilder.append(service);
		}
		paramMap.put("service", urlBuilder);
		paramMap.put("ticket", ticket);
		String data = HttpUtil.get(casHostValidateUrl, paramMap);
		data = StrUtil.removeAll(data, "\n");
		data = StrUtil.removeAll(data, "	");
		logger.debug(data);
		Document doc = XmlUtil.parseXml(data);
		Element element = XmlUtil.getRootElement(doc);
		NodeList nodes = element.getElementsByTagName("cas:user");
		Node node = nodes.item(0);
		String username = node.getTextContent();
		logger.debug(username);
		String tokent = JwtUtil.makeToken(username, tokenExpireTime);

		service = service.replace("!", "#");
		int qmIndex = service.indexOf('?');
		if (qmIndex > 0) {
			service += "&tokent=" + tokent;
		} else {
			service += "?tokent=" + tokent;
		}
		return "redirect:" + service;
	}

	@GetMapping("/login/sso")
	public String loginSso(String verify, String userName, String strSysDatetime, String jsName, HttpServletRequest request) {
		logger.debug(userName);
		String str = "535B15D3669104F2E183E21481E628012E6D7FF";
		String originalStr = userName + str + strSysDatetime + jsName;
		String encodeStr = getMd5Str(originalStr);

		if (encodeStr.toUpperCase().equals(verify.toUpperCase())) {
			String token = JwtUtil.makeToken(userName, tokenExpireTime);

			return "redirect:" + "/#/?tokent=" + token;
		} else {
			return "redirect:" + "/#/login";
		}
	}

	private String getMd5Str(String originalStr) {
		String result = "";
		try {
			MessageDigest md5 = MessageDigest.getInstance("md5");
			byte[] b = originalStr.getBytes();
			byte[] digest = md5.digest(b);
			char[] chars = new char[] { '0', '1', '2', '3', '4', '5',
					'6', '7' , '8', '9', 'A', 'B', 'C', 'D', 'E','F' };
			StringBuffer sb = new StringBuffer();
			for (byte bb : digest) {
				sb.append(chars[(bb >> 4) & 15]);
				sb.append(chars[bb & 15]);
			}
			result = sb.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

		return result;
	}

	private String getService(HttpServletRequest request) {
		String scheme = request.getHeader("x-scheme");
		if (StrUtil.isEmpty(scheme)) {
			scheme = request.getScheme();
		}
		StringBuilder service = new StringBuilder(scheme);
		service.append("://");
		service.append(request.getServerName());
		if (80 != request.getServerPort() && 443 != request.getServerPort()) {
			service.append(":");
			service.append(request.getServerPort());
		}
		service.append(request.getServletPath());
		return service.toString();
	}
}
